package io.gitee.zhangbinhub.admin.oauth.controller.api

import io.gitee.zhangbinhub.acp.boot.exceptions.WebException
import io.gitee.zhangbinhub.acp.boot.log.LogAdapter
import io.gitee.zhangbinhub.acp.cloud.annotation.AcpCloudDuplicateSubmission
import io.gitee.zhangbinhub.acp.core.common.CommonTools
import io.gitee.zhangbinhub.admin.common.api.OauthApi
import io.gitee.zhangbinhub.admin.common.permission.BaseExpression
import io.gitee.zhangbinhub.admin.common.vo.CustomerQueryPageVo
import io.gitee.zhangbinhub.admin.common.vo.InfoVo
import io.gitee.zhangbinhub.admin.oauth.bus.publish.RefreshEventPublish
import io.gitee.zhangbinhub.admin.oauth.constant.AppConfigExpression
import io.gitee.zhangbinhub.admin.oauth.service.ApplicationService
import io.gitee.zhangbinhub.admin.oauth.entity.Application
import io.gitee.zhangbinhub.admin.oauth.po.ApplicationPo
import io.gitee.zhangbinhub.admin.oauth.po.ApplicationQueryPo
import io.gitee.zhangbinhub.admin.resource.server.base.BaseResourceServerController
import io.swagger.v3.oas.annotations.*
import io.swagger.v3.oas.annotations.responses.ApiResponse
import io.swagger.v3.oas.annotations.responses.ApiResponses
import io.swagger.v3.oas.annotations.tags.Tag
import jakarta.validation.Valid
import jakarta.validation.constraints.NotBlank
import jakarta.validation.constraints.NotEmpty
import jakarta.validation.constraints.NotNull
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.domain.Page
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.*

/**
 * @author zhang by 13/01/2019
 * @since JDK 11
 */
@Validated
@RestController
@RequestMapping(OauthApi.basePath)
@Tag(name = "应用信息")
class ApplicationController @Autowired constructor(
    logAdapter: LogAdapter,
    private val applicationService: ApplicationService,
    private val refreshEventPublish: RefreshEventPublish
) : BaseResourceServerController(logAdapter) {

    @Operation(summary = "新建应用信息", description = "应用名称、token 有效期、refresh token 有效期")
    @ApiResponses(ApiResponse(responseCode = "201", description = "创建成功"))
    @PreAuthorize(AppConfigExpression.appAdd)
    @PutMapping(value = [OauthApi.appConfig], produces = [MediaType.APPLICATION_JSON_VALUE])
    @AcpCloudDuplicateSubmission
    fun add(@RequestBody @Valid applicationPo: ApplicationPo): ResponseEntity<Application> =
        applicationService.doCreate(applicationPo).also {
            refreshEventPublish.doNotifyUpdateApp()
        }.let {
            ResponseEntity.status(HttpStatus.CREATED).body(it)
        }

    @Operation(summary = "删除指定的信息")
    @ApiResponses(ApiResponse(responseCode = "400", description = "参数校验不通过；"))
    @PreAuthorize(AppConfigExpression.appDelete)
    @DeleteMapping(value = [OauthApi.appConfig], produces = [MediaType.APPLICATION_JSON_VALUE])
    fun delete(
        @Parameter(
            name = "id列表", required = true
        ) @NotEmpty(message = "id不能为空") @NotNull(message = "id不能为空") @RequestBody idList: MutableList<String>
    ): ResponseEntity<InfoVo> {
        applicationService.doDelete(idList)
        refreshEventPublish.doNotifyUpdateApp()
        return ResponseEntity.ok(InfoVo(message = "删除成功"))
    }

    @Operation(summary = "更新指定的信息", description = "可更新应用名称、token 有效期、refresh token 有效期")
    @ApiResponses(ApiResponse(responseCode = "400", description = "参数校验不通过；ID不能为空；找不到信息；"))
    @PreAuthorize(AppConfigExpression.appUpdate)
    @PatchMapping(value = [OauthApi.appConfig], produces = [MediaType.APPLICATION_JSON_VALUE])
    @AcpCloudDuplicateSubmission
    @Throws(WebException::class)
    fun update(@RequestBody @Valid applicationPo: ApplicationPo): ResponseEntity<Application> {
        if (CommonTools.isNullStr(applicationPo.id)) {
            throw WebException("ID不能为空")
        }
        return applicationService.doUpdate(applicationPo).also {
            refreshEventPublish.doNotifyUpdateApp()
        }.let {
            ResponseEntity.ok(it)
        }
    }

    @Operation(summary = "查询信息列表", description = "查询条件：应用名称")
    @ApiResponses(ApiResponse(responseCode = "400", description = "参数校验不通过；"))
    @PreAuthorize(AppConfigExpression.appQuery)
    @PostMapping(value = [OauthApi.appConfig], produces = [MediaType.APPLICATION_JSON_VALUE])
    @Throws(WebException::class)
    fun query(@RequestBody @Valid applicationQueryPo: ApplicationQueryPo): ResponseEntity<CustomerQueryPageVo<Application>> =
        ResponseEntity.ok(applicationService.doQuery(applicationQueryPo))

    @Operation(summary = "获取应用列表", description = "查询所有应用列表")
    @PreAuthorize(BaseExpression.sysConfig)
    @GetMapping(value = [OauthApi.appConfig], produces = [MediaType.APPLICATION_JSON_VALUE])
    fun appList(): ResponseEntity<List<Application>> = ResponseEntity.ok(applicationService.getAppList())

    @Operation(summary = "更新应用密钥")
    @ApiResponses(ApiResponse(responseCode = "400", description = "参数校验不通过；ID不能为空；找不到信息；"))
    @PreAuthorize(AppConfigExpression.appUpdateSecret)
    @GetMapping(value = [OauthApi.updateSecret + "/{appId}"], produces = [MediaType.APPLICATION_JSON_VALUE])
    @AcpCloudDuplicateSubmission
    @Throws(WebException::class)
    fun updateSecret(
        @Parameter(description = "应用id", required = true)
        @NotBlank(message = "应用id不能为空")
        @PathVariable(name = "appId") appId: String
    ): ResponseEntity<Application> = applicationService.doUpdateSecret(appId).also {
        refreshEventPublish.doNotifyUpdateApp()
    }.let {
        ResponseEntity.ok(it)
    }

}
